=begin pod :tag<perl6>

=TITLE Modules

=SUBTITLE How to create, use and distribute Perl 6 modules

=head1 Creating and Using Modules

A module is usually a source file or set of source files N<Technically
a module is a set of I<compunits> which are usually files but could
come from anywhere as long as there is a I<compunit repository> that
can provide it. See L<S11|https://design.perl6.org/S11.html>.> that
expose Perl 6 constructs. These are typically packages
(L<classes|/language/objects#Classes>,
L<roles|/language/objects#Roles>, L<grammars|Grammar>),
L<subroutines|/language/functions>, and sometimes
L<variables|/language/variables>. In Perl 6 I<module> can also refer
to a type of package declared with the C<module> keyword (see example
below) but here we mostly mean "module" as a set of source
files in a namespace.

=head2 Basic Structure

Module distributions (in the I<set of related source files> sense) in Perl 6
have the same structure as any distribution in the Perl family of languages:
there is a main project directory containing a C<README> and a C<LICENSE> file,
a C<lib> directory for the source files, which may be individually
referred to as modules and/or may themselves define modules with the C<module>
keyword N<As L<synopsis S11|https://design.perl6.org/S11.html#Units> says:
Confusing? Yes it is.>, a C<t> directory for tests, and possibly a C<bin>
directory for executable programs and scripts.

Source files generally use the C<.pm6> extension, and scripts or
executables use the C<.p6>. Test files use the C<.t> extension.

=head2 Loading and Basic Importing

Loading a module makes the packages in the same namespace declared
within available in the file scope of the loader. Importing from a
module makes the symbols exported available in the lexical scope of
the importing statement.

=head3 X<need|compunit>

C<need> loads a C<compunit> at compile time.

=for code :skip-test
need MyModule;

Any packages in the namespace defined within will also be available.

=begin code :skip-test
# MyModule.pm6
unit module MyModule;

class MyModule::Class {}
=end code

C<MyModule::Class> will be defined when C<MyModule> is loaded.

=comment class Class { ... } won't get exported automatically on loading...not sure if bug or..

=head3 X<use|compunit>

C<use> loads and then imports from a compunit at compile time. It will look for
files that end in C<.pm6> (C<.pm> is also supported). See
L<here|/language/modules#Finding_Modules>
for where the runtime will look for modules.

=for code :skip-test
use MyModule;

It is equivalent to:

=begin code :allow<L> :skip-test
L<need|/language/modules#need> MyModule;
import MyModule;
=end code

See also L<Selective Importing|/language/modules#Exporting_and_Selective_Importing> to restrict what you import.

=head3 X<require|compunit>

C<require> loads a compunit and imports definite symbols at runtime.

    say "loading MyModule";
    require MyModule;

The compunit name can be in a runtime variable if you put it inside an
indirect lookup.

    my $name = 'MyModule';
    require ::($name);

The symbols provided by the loaded module will not be imported into the current
scope. You may use L<dynamic lookup|/language/packages#index-entry-::()> or
L<dynamic subsets|/language/typesystem#subset> to use them by providing the
fully qualified name of a symbol.

To import symbols you must define them at compile time. B<NOTE:> C<require>
is lexically scoped:

    sub do-something {
       require MyModule <&something>;
       say ::('MyModule'); # MyModule symbol exists here
       something() # &something will be defined here
    }
    say ::('MyModule'); # This will NOT contain the MyModule symbol
    do-something();
    # &something will not be defined here

If C<MyModule> doesn't export C<&something> then C<require> will fail.

A C<require> with compile-time symbol will install a placeholder C<package>
that will be updated to the loaded module, class, or package. Note that the
placeholder will be kept, B<even if require failed to load the module.>
This means that checking if a module loaded like this is wrong:

    # *** WRONG: ***
    try require Foo;
    if ::('Foo') ~~ Failure { say "Failed to load Foo!"; }
    # *** WRONG: ***

As the compile-time installed package causes C<::('Foo')> to never be
a C<Failure>. The correct way is:

    # Use return value to test whether loading succeeded:
    (try require Foo) === Nil and say "Failed to load Foo!";

    # Or use a run-time symbol lookup with require, to avoid compile-time
    # package installation:
    try require ::('Foo');
    if ::('Foo') ~~ Failure {
        say "Failed to load Foo!";
    }

=head2 Exporting and Selective Importing

=head3 is export

Packages, subroutines, variables, constants and enums are exported by marking
them with the L<is export> trait (also note the tags available for indicating authors and versions).

    =begin code :skip-test
    unit module MyModule:ver<1.0.3>:auth<John Hancock (jhancock@example.com)>;
    our $var is export = 3;
    sub foo is export { ... };
    constant FOO is export = "foobar";
    enum FooBar is export <one two three>;

    # Packages like classes can be exported too
    class MyClass is export {};

    # If a subpackage is in the namespace of the current package
    # it doesn't need to be explicitly exported
    class MyModule::MyClass {};
    =end code

As with all traits, if applied to a routine, "is export" should appear after
any argument list.

    =begin code :skip-test
    sub foo(Str $string) is export { ... }
    =end code

You can pass named parameters to C<is export> to group symbols for exporting
so that the importer can pick and choose. There are three predefined
tags: C<ALL>, C<DEFAULT> and C<MANDATORY>.

    =begin code :skip-test
    # lib/MyModule.pm6
    unit module MyModule;
    sub bag        is export             { ... }
    sub pants      is export(:MANDATORY) { ... } # objects with tag ':MANDATORY' are always exported
    sub sunglasses is export(:day)       { ... }
    sub torch      is export(:night)     { ... }
    sub underpants is export(:ALL)       { ... }
    =end code

    =begin code :skip-test
    # main.p6
    use lib 'lib';
    use MyModule;          # bag, pants
    use MyModule :DEFAULT; # the same
    use MyModule :day;     # pants, sunglasses
    use MyModule :night;   # pants, torch
    use MyModule :ALL;     # bag, pants, sunglasses, torch, underpants
    =end code

Note there currently is no way for the user to import a single object if
the module author hasn't made provision for that, and it is not an easy
task at the moment (see RT #127305). One way the author can provide
such access is to give each C<export> trait its own unique tag. (And the tag
can be the object name!) Then the user can either (1) import all objects:

    =begin code :skip-test
    use Foo :ALL;
    =end code

or (2) import one or more objects selectively:

    =begin code :skip-test
    use Foo :bar, :s5;
    =end code

Notes:

1. The C<:MANDATORY> tag on an exported sub ensures it will be exported
no matter whether the using program adds any tag or not.

2. All exported subs without an explicit tag are implicitly C<:DEFAULT>.

3. The space after the module name and before the tag is mandatory.

4. Multiple import tags may be used (separated by commas).  For example:

    =begin code :skip-test
    # main.p6
    use lib 'lib';
    use MyModule :day, :night; # pants, sunglasses, torch
    =end code

5. Multiple tags may be used in the C<export> trait, but they must
   all be separated by either commas, or whitespace, but not both.

   =begin code
   sub foo() is export(:foo :s2 :net) {}
   sub bar() is export(:bar, :s3, :some) {}
   =end code

=head3 UNIT::EXPORT::*

Beneath the surface, C<is export> is adding the symbols to a C<UNIT>
scoped package in the C<EXPORT> namespace. For example, C<is
export(:FOO)> will add the target to the C<UNIT::EXPORT::FOO>
package. This is what Perl 6 is really using to decide what to import.

    =begin code :skip-test
    unit module MyModule;

    sub foo is export { ... }
    sub bar is export(:other) { ... }
    =end code

Is the same as:

    =begin code :skip-test
    unit module MyModule;

    my package EXPORT::DEFAULT {
        our sub foo { ... }
    }

    my package EXPORT::other {
        our sub bar { ... }
    }
    =end code

For most purposes C<is export> is sufficient but the C<EXPORT>
packages are useful when you want to produce the exported symbols
dynamically. For example:

    =begin code :skip-test
    # lib/MyModule.pm6
    unit module MyModule;

    my package EXPORT::DEFAULT {
       for <zero one two three four>.kv -> $number, $name {
          for <sqrt log> -> $func {
             OUR::{'&' ~ $func ~ '-of-' ~ $name } := sub { $number."$func"() };
          }
       }
    }

    =end code

    =begin code :skip-test
    # main.p6
    use MyModule;
    say sqrt-of-four; # OUTPUT: «2␤»
    say log-of-zero;  # OUTPUT: «-Inf␤»
    =end code

=head3 EXPORT
X<|sub EXPORT>

You can export arbitrary symbols with an C<EXPORT> sub. C<EXPORT>
must return a L<Map>, where the keys are the symbol names and
the values are the desired values. The names should include the sigil
(if any) for the associated type.

    =begin code :skip-test
    # lib/MyModule.pm6

    class MyModule::Class { }

    sub EXPORT {
        %(
          '$var'      => 'one',
          '@array'    => <one two three>,
          '%hash'     => %( one => 'two', three => 'four' ),
          '&doit'     => sub { say 'Greetings from exported sub' },
          'ShortName' => MyModule::Class
        )
    }
    =end code

    =begin code :skip-test
    # main.p6
    use lib 'lib';
    use MyModule;
    say $var;          # OUTPUT: «one␤»
    say @array;        # OUTPUT: «(one two three)␤»
    say %hash;         # OUTPUT: «{one => two, three => four}␤»
    doit();            # OUTPUT: «Greetings from exported sub␤»
    say ShortName.new; # OUTPUT: «MyModule::Class.new␤»
    =end code

Note, C<EXPORT> can't be declared inside a package because
it is part of the compunit rather than the package.

Whereas C<UNIT::EXPORT> packages deal with the named parameters passed
to C<use>, the C<EXPORT> sub handles positional parameters. If you
pass positional parameters to C<use> they will be passed to
C<EXPORT>. If a positional is passed the module no longer exports
default symbols. You may still import them explicitly by
passing C<:DEFAULT> to C<use> along with your positional parameters.

    =begin code
    # lib/MyModule

    class MyModule::Class {}

    sub EXPORT($short_name?) {
        %(
          do $short_name => MyModule::Class if $short_name
        )
    }

    sub always is export(:MANDATORY) { say "works" }

    #import with :ALL or :DEFAULT to get
    sub shy is export { say "you found me!" }
    =end code

    =begin code :skip-test
    # main.p6
    use lib 'lib';
    use MyModule 'foo';
    say foo.new(); # OUTPUT: «MyModule::Class.new␤»

    always();      # OK   - is imported
    shy();         # FAIL - won't be imported
    =end code

You can combine `EXPORT` with type captures for interesting
effect. This example creates a `?` postfix which will only work on
L<Cool>s.

    =begin code :skip-test
    # lib/MakeQuestionable.pm6
    sub EXPORT(::Questionable) {
        my multi postfix:<?>(Questionable $_) { .so };
        %(
          '&postfix:<?>' => &postfix:<?>,
        )
    }
    =end code

    =begin code :skip-test
    use MakeQuestionable Cool;
    say ( 0?, 1?, {}?, %( a => "b" )? ).join(' '); # OUTPUT: «False True False True␤»
    =end code

=head2 Introspection

To list exported symbols of a module first query the export tags supported by
the module.

    use URI::Escape;
    say URI::Escape::EXPORT::.keys;
    # OUTPUT: «(DEFAULT ALL)␤»

Then use the tag you like and pick the symbol by its name.

    say URI::Escape::EXPORT::DEFAULT::.keys;
    # OUTPUT: «(&uri-escape &uri-unescape &uri_escape &uri_unescape)␤»
    my &escape-uri = URI::Escape::EXPORT::DEFAULT::<&uri_escape>;

=head2 Finding Modules

It is up to the module installer to know where C<compunit> expects modules to
be placed. There will be a location provided by the distribution and in the
current home directory. In any case, letting the module installer deal with
your modules is a safe bet.

    =begin code :skip-test<io>
    cd your-module-dir
    zef --force install .
    =end code

X<|use lib>
A user may have a collection of modules not found in the normal ecosystem,
maintained by a module or package manager, but needed regularly.  Instead of
using the C<use lib> pragma one can use the C<PERL6LIB> environment variable to
point to module locations.  For example:

=for code :lang<shell>
export PERL6LIB=/path/to/my-modules,/path/to/more/modules

Note that the comma (',') is used as the directory separator.

The include path will be searched recursively for any modules when Rakudo is
started. Directories that start with a dot are ignored and symlinks are
followed.

=head1 Distributing Modules

If you've written a Perl 6 module and would like to share it with the
community, we'd be delighted to have it listed in the L<Perl 6 modules
directory|https://modules.perl6.org>. C<:)>

Currently there are two different module ecosystems (module distribution
networks) available:

    =item B<CPAN>
    This is the same ecosystem Perl5 is using. Modules are uploaded as I<.zip>
    or I<.tar.gz> files on L<PAUSE|https://pause.perl.org/>.

    =item B<p6c>
    Up until recently the only ecosystem, but soon to be deprecated. It is based
    on Github repositories which are directly accessed. It has only limited
    capability for versioning.

The process of sharing your module consists of two steps, preparing the module
and uploading the module to one of the ecosystems.

=head2 Preparing the Module

For a module to work in any of the ecosystems, it needs to follow a certain
structure. Here is how to do that:

    =item Create a project directory named after your module. For
    example, if your module is C<Vortex::TotalPerspective>, then create a
    project directory named C<Vortex-TotalPerspective>.

    =begin item
    Make your project directory look like this:

=begin code :skip-test
Vortex-TotalPerspective/
|-- lib
|   `-- Vortex
|       `-- TotalPerspective.pm6
|-- LICENSE
|-- META6.json
|-- README.md
`-- t
    `-- basic.t


=end code

    If your project contains other modules that help the main module do
    its job, they should go in your lib directory like so:

=begin code :skip-test
lib
`-- Vortex
    |-- TotalPerspective.pm6
    `-- TotalPerspective
        |-- FairyCake.pm6
        `-- Gargravarr.pm6
=end code
    =end item

    =item If you have any additional files (such as templates or a dynamic
    library) that you wish to have installed so you can access them at
    runtime, they should be placed in a C<resources> sub-directory of your project.

    =item The C<README.md> file is a L<markdown-formatted|https://help.github.com/articles/markdown-basics/>
    text file, which will later be automatically rendered as HTML by GitHub.

    =item Regarding the C<LICENSE> file, if you have no other preference,
    you might just use the same one that Rakudo Perl 6 uses. Just
    copy/paste the raw form of L<its license|https://github.com/rakudo/rakudo/blob/master/LICENSE>
    into your own C<LICENSE> file.

    =item The license field in META6.json
    The license field should be one of the standardized names listed here:
    https://spdx.org/licenses/, in the case of the B<Artistic 2.0> license which
    is what many of our ecosystem modules use, its identifier is
    C<Artistic-2.0>. Having standardized identifiers make it easy for humans
    and computers alike to know which license was actually used by looking at
    the metadata!

    =item My license is not on spdx.org or using your own license
    If you can't find your license on C<spdx.org> or you use your own license,
    you should put the licenses name in the license field, and under
    more details here https://design.perl6.org/S22.html#license

    =item If you don't yet have any tests, you can leave out the C<t>
    directory and C<basic.t> file for now. For more info on how to write
    tests (for now), you might have a look at how other modules use
    C<Test>.

    =begin item
    To document your modules, use L<Perl 6 Pod |
    https://design.perl6.org/S26.html> markup inside your modules. Module
    documentation is most appreciated and will be especially important once
    the Perl 6 module directory (or some other site) begins rendering Pod docs
    as HTML for easy browsing. If you have extra docs (in addition to the
    Pod docs in your module(s)), create a C<doc> directory for them. Follow
    the same folder structure as the C<lib> directory like so:

    =begin code :skip-test
    doc
    `-- Vortex
        `-- TotalPerspective.pod6
    =end code

    =end item

    =item
    Note, described above is a minimal project directory. If your project
    contains scripts that you'd like distributed along with your module(s),
    put them in a C<bin> directory. If you'd like a graphical logo to
    appear next to your module at the module directory, create a
    C<logotype> directory and put into it a C<logo_32x32.png> file. At some
    point, you might also consider adding C<CONTRIBUTORS>, C<NEWS>,
    C<TODO>, or other files.

    =begin item
    Make your X<C<META6.json>|META6.json> file look something like this:

    =begin code :allow<R>
    {
        "perl" : "6.c",
        "name" : "Vortex::TotalPerspective",
        "version" : "0.0.1",
        "description" : "Wonderful simulation to get some perspective.",
        "authors" : [ "R<Your Name>" ],
        "license" : "Artistic-2.0",
        "provides" : {
            "Vortex::TotalPerspective" : "lib/Vortex/TotalPerspective.pm6"
        },
        "depends" : [ ],
        "resources" : [ ],
        "source-url" : "git://github.com/R<you>/Vortex-TotalPerspective.git"
    }
    =end code

    For choosing a version numbering scheme, perhaps use
    "major.minor.patch" (see L<the spec on versioning |
    https://design.perl6.org/S11.html#Versioning> for further
    details). If the version number doesn't matter to you or your users
    right now, you can just put in an asterisk (*) for the version.

    The C<authors> section includes a list of all the module authors. In
    the case there is only one author, a single element list must be
    supplied.

    In the C<provides> section, include all the namespaces provided by
    your distribution and that you wish to be installed, only module
    files that are explicitly included here will be installed and
    available with C<use> or C<require> in other programs.

    Set C<perl> version to the minimum perl version your module works with.

    The C<resources> section is optional, but, if present, should contain a
    list of the files in your C<resources> directory that you wish to be
    installed, these will be installed with hashed names alongside your
    library files and their installed location can be determined through the
    C<%?RESOURCES> Hash indexed on the name provided.

    The L<Test::META module | https://github.com/jonathanstowe/Test-META/>
    can help you check the correctness of the META6.json file.

    There are more fields described in the L<META design documents |
    https://design.perl6.org/S22.html#META6.json>, but not all of these are
    implemented by existing package managers. Hence you should stick to the
    fields described in the above example block to ensure compatibility with
    existing package managers.

    =end item

    =begin item
    To test your module you can use the following command to install the
    module directly from the module folder you just created.

    =begin code :lang<shell>
    zef install ./your-module-folder
    =end code

    =end item

=head2 Upload your Module to CPAN

Uploading a module to CPAN is the preferred way of distributing Perl 6 modules.

it requires having a L<PAUSE|https://pause.perl.org/>
user account. If you don't have an account already go there and apply for an
account. The process takes about 5 minutes and some e-mail back and forth.

    =begin item
    Create a package of your module:

    =begin code :lang<shell>
    cd your-module-folder
    tar czf Vortex-TotalPerspective-0.0.1.tar.gz --transform s/^\./Vortex-TotalPerspective-0.0.1/ --exclude-vcs --exclude=.[^/]*
    =end code

    If you use git you can also use the following command to create a package directly for a given commit.

    =begin code :lang<shell>
    git archive --prefix=Vortex-TotalPerspective-0.0.1/ -o ../Vortex-TotalPerspective-0.0.1.tar.gz HEAD
    =end code

    =end item

    =item Go to L<PAUSE|https://pause.perl.org/>, log in and click on
    L<Upload a file to CPAN|https://pause.perl.org/pause/authenquery?ACTION=add_uri>.

    =item Make sure you select C<Perl6> as the I<Target Directory>. For
    your first upload, you have to enter the string C<Perl6> in the text field.
    On subsequent uploads, you can select the C<Perl6> directory from select
    box above the input field.

    =begin item
    Select your file and click I<Upload>!

    I<Make sure you have a META6.json file in your dist and that the dist
    version you're uploading is higher than the currently uploaded version.
    Those are the most common upload errors.>

    =end item

=head2 Upload your Module to p6c

I<The p6c ecosystem is soon to be deprecated, so you should consider
using the CPAN ecosystem instead.>

If you want to use the I<p6c> ecosystem you need to use git for your module's
version control. The instructions herein assume that you have a
L<GitHub|https://github.com> account so that your module can be shared from its
GitHub repository, however another provider such as
L<GitLab|https://about.gitlab.com/> should work as long as it works in a
similar way.

    =item Put your project under git version control if you haven't done so
    already.

    =item Once you're happy with your project, create a repository for it on GitHub.
    See L<GitHub's help docs|https://help.github.com/> if necessary. Your
    GitHub repository should be named the same as your project directory. Immediately
    after creating the GitHub repo, GitHub shows you how to configure your
    local repository to know about your GitHub repository.

    =item Push your project to GitHub.

    =item Consider setting up automated testing (see L<https://docs.travis-ci.com/user/languages/perl6>).

    =item Create a PR on L<ecosystem|https://github.com/perl6/ecosystem> adding
    your module to META.list, or ping someone on IRC (#perl6 at freenode) to
    get help having it added.

    =item After the pull request has been accepted, wait for an hour. If
    your module doesn't show up on L<https://modules.perl6.org/>, please
    view the log file at L<https://modules.perl6.org/update.log> to see
    if it identifies an error with your module or meta file.

B<That's it! Thanks for contributing to the Perl 6 community!>

If you'd like to try out installing your module, use the X<zef> module
installer tool which is included with Rakudo Star Perl 6:

=begin code :lang<shell>
zef install Vortex::TotalPerspective
=end code

This will download your module to its own working directory (C<~/.zef>),
build it there, and install the module into your local Perl 6 installation directory.

To use C<Vortex::TotalPerspective> from your scripts, just write
C<use Vortex::TotalPerspective>, and your Perl 6 implementation will
know where to look for the module file(s).

=head1 Modules and Tools Related to Module Authoring

You can find a list of modules and tools that aim to improve the experience of
writing/test modules at L<Modules Extra|/language/modules-extra>

=head2 Contact Information

To discuss module development in general, or if your module would
fill a need in the ecosystem, naming, etc., you can use the
L<#perl6 on irc.freenode.net|irc://irc.freenode.net/#perl6> IRC channel.

To discuss toolchain specific questions, you can use the
L<#perl6-toolchain on irc.freenode.net|irc://irc.freenode.net/#perl6-toolchain>
IRC channel. A repository to discuss tooling issues is also available at
L<https://github.com/perl6/toolchain-bikeshed>.

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
